# encoding=utf-8

import time
import sys
import hashlib
import hmac
import base64
import stomp
import ssl
import schedule
import threading
import os
import json


# 文件路径，可根据需要修改
GPS_FILE_PATH = 'gps_data.txt'

# 写入 GPS 数据，每次写一条，最多保存 10 条，超过后循环覆盖
def write_gps_data_to_file(gps_data):
    # 如果文件不存在，则创建并初始化为空列表
    if not os.path.exists(GPS_FILE_PATH):
        with open(GPS_FILE_PATH, 'w', encoding='utf-8') as f:
            json.dump([], f)

    # 读取已有数据
    with open(GPS_FILE_PATH, 'r', encoding='utf-8') as f:
        try:
            data_list = json.load(f)
        except json.JSONDecodeError:
            data_list = []

    # 写入数据（循环覆盖10条）
    if len(data_list) < 10:
        data_list.append(gps_data)
    else:
        # 使用循环覆盖逻辑：记录写入的索引
        index_file = GPS_FILE_PATH + '.idx'
        if os.path.exists(index_file):
            with open(index_file, 'r') as f:
                index = int(f.read().strip())
        else:
            index = 0

        data_list[index] = gps_data
        index = (index + 1) % 10  # 环形索引

        with open(index_file, 'w') as f:
            f.write(str(index))

    # 保存更新后的数据
    with open(GPS_FILE_PATH, 'w', encoding='utf-8') as f:
        json.dump(data_list, f, ensure_ascii=False, indent=2)

def connect_and_subscribe(conn):
    # 工程代码泄露可能会导致 AccessKey 泄露，并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用，仅供参考
    accessKey = "LTAI5tPHjnSemGAkQ6myYpND"
    accessSecret = "wvBsiuu93n1nDTdSwOxF0d0XOiGeCr"
    consumerGroupId = "DEFAULT_GROUP"
    # iotInstanceId：实例ID。
    iotInstanceId = "iot-06z00dah49qr35d"
    clientId = "Remote_App"
    # 签名方法：支持hmacmd5，hmacsha1和hmacsha256。
    signMethod = "hmacsha1"
    timestamp = current_time_millis()
    # userName组装方法，请参见AMQP客户端接入说明文档。
    # 若使用二进制传输，则userName需要添加encode=base64参数，服务端会将消息体base64编码后再推送。具体添加方法请参见下一章节“二进制消息体说明”。
    username = clientId + "|authMode=aksign" + ",signMethod=" + signMethod \
                + ",timestamp=" + timestamp + ",authId=" + accessKey \
                + ",iotInstanceId=" + iotInstanceId \
                + ",consumerGroupId=" + consumerGroupId + "|"
    signContent = "authId=" + accessKey + "&timestamp=" + timestamp
    # 计算签名，password组装方法，请参见AMQP客户端接入说明文档。
    password = do_sign(accessSecret.encode("utf-8"), signContent.encode("utf-8"))
    
    conn.set_listener('', MyListener(conn))
    conn.connect(username, password, wait=True)
    # 清除历史连接检查任务，新建连接检查任务
    schedule.clear('conn-check')
    schedule.every(1).seconds.do(do_check, conn).tag('conn-check')

class MyListener(stomp.ConnectionListener):
    def __init__(self, conn):
        self.conn = conn

    def on_error(self, frame):
        print('received an error "%s"' % frame.body)

    def on_message(self, frame):
        print('received a message raw: "%s"' % frame.body)
        try:
            message_json = json.loads(frame.body)
            print('decoded JSON message:', json.dumps(message_json, ensure_ascii=False, indent=2))
            
            # 将解析到的GPS数据存储到数组中，直接存储为浮点数
            gps_data = {
                "LBSLON": float(message_json.get("LBSLON", 0)),  # 默认值为0，避免解析失败
                "LBSLAT": float(message_json.get("LBSLAT", 0))   # 默认值为0，避免解析失败
            }
            print("GPS data added to dict:", gps_data)
            write_gps_data_to_file(gps_data)
        except json.JSONDecodeError as e:
            print("JSON decode error:", e)
        except ValueError as e:
            print("Value error (e.g., non-numeric value):", e)

    def on_heartbeat_timeout(self):
        print('on_heartbeat_timeout')

    def on_connected(self, headers):
        print("successfully connected")
        self.conn.subscribe(destination='/topic/#', id=1, ack='auto')
        print("successfully subscribe")

    def on_disconnected(self):
        print('disconnected')
        connect_and_subscribe(self.conn)

def current_time_millis():
    return str(int(round(time.time() * 1000)))

def do_sign(secret, sign_content):
    m = hmac.new(secret, sign_content, digestmod=hashlib.sha1)
    return base64.b64encode(m.digest()).decode("utf-8")

# 检查连接，如果未连接则重新建连
def do_check(conn):
    print('check connection, is_connected: %s', conn.is_connected())
    if (not conn.is_connected()):
        try:
            connect_and_subscribe(conn)
        except Exception as e:
            print('disconnected, ', e)

# 定时任务方法，检查连接状态
def connection_check_timer():
    while 1:
        schedule.run_pending()
        time.sleep(10)

# 接入域名，请参见AMQP客户端接入说明文档。这里直接填入域名，不需要带amqps://前缀
conn = stomp.Connection([('iot-06z00dah49qr35d.amqp.iothub.aliyuncs.com', 61614)], heartbeats=(0,300))
conn.set_ssl(for_hosts=[('iot-06z00dah49qr35d.amqp.iothub.aliyuncs.com', 61614)], ssl_version=ssl.PROTOCOL_TLS)

try:
    connect_and_subscribe(conn)
except Exception as e:
    print('connecting failed')
    raise e
    
# 异步线程运行定时任务，检查连接状态
thread = threading.Thread(target=connection_check_timer)
thread.start()